昨天和前天是介紹如何使用 Docker 提供的 Restful API,操作啟動 Docker Container,這樣可以透過程式方便建立測試環境,對撰寫測試程式建構環境方面有幫助。
今天要介紹的部份是在開發完程式之後會 Build 成一個檔案, 然後把這個程式包在 Docker Image 內,這樣使用者要使用此程式時,也就可以不用安裝或佈署此檔案,只要執行 docker run
指令就可以把程式執行起來。
今天就來寫個簡單的 Akka HTTP 程式,並且透過使用 SBT Build Tool 來打包 Docker Image。
在執行 sbt build
的指令時就把撰寫的 Akka Http 程式打包到成 Docker Image,之後再使用 docker run
指令把 Container 啟動起來。
一. 我把此程式放在 GitHub 上,如果有興趣的話可以直接 clone 到 local 測試,指令如下:
$ git clone https://github.com/jackyoh/akkahttp-docker-example.git
二. Akka HTTP 程式和說明如下:
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.stream.ActorMaterializer
import scala.io.StdIn
object AkkaHTTPExample {
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val route =
path("hello") {
get {
complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to Akka</h1>"))
}
}
Http().bindAndHandle(route, "0.0.0.0", 8080)
}
}
以上的程式主要是啟動一個 Akka HTTP Web Server,並且程式裡有實作一個方法,只要使用者輸入 /hello 的 URL 就會印出 Say hello to Akka 字串。
設定 SBT 的方式如下:
project/plugins.sbt
addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.4.1")
加入 sbt-docker 的 plugin
build.sbt
的程式內容如下:name := "akkahttp-docker-example"
version := "0.1-SNAPSHOT"
scalaVersion := "2.11.11"
val akkaVersion = "2.4.16"
val akkaHttpVersion = "10.0.3"
val slf4jVersion = "1.7.25"
val sprayJsonVersion = "1.3.3"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-stream" % akkaVersion,
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % "test",
"io.spray" %% "spray-json" % sprayJsonVersion,
"org.slf4j" % "slf4j-simple" % slf4jVersion
)
enablePlugins(DockerPlugin)
dockerfile in docker := {
val appPath = "/app"
val jarFile: File = sbt.Keys.`package`.in(Compile, packageBin).value
val classpath = (managedClasspath in Compile).value
val mainclass = "idv.jack.example.AkkaHTTPExample"
val jarTarget = s"${appPath}/${jarFile.getName}"
val classpathString = classpath.files.map(s"${appPath}/" + _.getName)
.mkString(":") + ":" + jarTarget + ":."
new Dockerfile {
from("java")
add(classpath.files, s"${appPath}/")
add(jarFile, jarTarget)
entryPoint("java", "-cp", classpathString, mainclass)
}
}
這裡主要的重點在 dockerfile in docker
這一段,主要是把程式使用的第三方 Jar 檔和 Project 的 Jar,複製進去 Docker Image 裡面,最後在用 Docker 的 entryPoint
設定 Docker run 裡執行啟動此 Project 的 Jar 檔。
四. 把程式打包成 Docker Image 的指令如下
$ sbt docker
輸入以上的指令就可以把程式打包成 Docker 的 Image,這裡要注意執行這個指令的使用者是否有執行 docker 指令的權限。
五. 使用 docker run
指令測試
$ docker run -d -p 9090:8080 --restart=always default/akkahttp-docker-example
執行結果如下
今天已經介紹了要如何把 Build 完成的 Jar,打包到 Docker Image 內,可以方便使用者使用,明天繼續介紹要如何的把此 Docker Image push 到 Docker Hub 上。